﻿Imports LabJack.LabJackUD.U3
Imports USA411.U3Config
Imports System.Data

''' <summary>
''' USA411.LJU3Port library. © 2008 ConPro, Inc. all rights reserved.
''' Use of this software in a non-commercial product permitted with clear © credit 
''' Use of this software in a commercial product, by license only 
''' </summary>
''' <remarks></remarks>
Public Class LJU3Port
    Public Event StateChange(ByVal _PortID As Byte, ByVal ActionID As Integer, ByVal State As Boolean, ByVal _TimeInState As TimeSpan)
    Private iHandle As Integer
    Private _CurrentSkipCounter As Byte = 0 'If we only need to check this very infreequently, then
    ' this can be set to only trigger every X cycles. The duration of a cycle is determined by the
    ' consuming Class (USA411.LJU3) and the application that consumes it.
    Private _CurrentDebounce As Byte = 0    'Some devices can triggure inappropriately due to a number
    ' of causes (Lightning on an IR Motion detector) or an occasional static build up that can trigger
    ' A false trip. The value you set here will be the numbor of consecutive cycles that the state must
    ' remain the same for it to be treated as a state change.
    Private _CurrentState As Boolean
    Private _ReportedState As Boolean
    Private _StateStartTime As Date

#Region "Overloaded Constructors Here"
    ' A number of overloaded constructors to make the use more flexable, however it is the responsibility
    ' of the developer to make sure all required properties and parameters have been supplied before 
    ' attempting to use the functions
    'Sub New(ByRef pHandle As Integer)
    '    iHandle = pHandle
    '    _StateStartTime = Now
    'End Sub
    'Sub New(ByRef pHandle As Integer, ByVal PortNum As Byte)
    '    _PortID = PortNum
    '    iHandle = pHandle
    '    _StateStartTime = Now
    'End Sub
    'Sub New(ByRef pHandle As Integer, ByVal PortNum As Byte, ByVal SkipCounter As Byte)
    '    iHandle = pHandle
    '    _PortID = PortNum
    '    _SkipCounter = SkipCounter
    '    _StateStartTime = Now
    'End Sub
    'Sub New(ByRef pHandle As Integer, ByVal PortNum As Byte, ByVal SkipCounter As Byte, ByVal DebounceCycleCount As Byte)
    '    iHandle = pHandle
    '    _PortID = PortNum
    '    _SkipCounter = SkipCounter
    '    _DeBounceCycles = DebounceCycleCount
    '    _StateStartTime = Now
    'End Sub
    Sub New(ByRef pHandle As Integer, ByVal Crow As DataRow)
        iHandle = pHandle
        _DeviceID = Crow.Item("DeviceID")
        _PortID = Crow.Item("PortID")
        _PortType = Crow.Item("PortType")
        _Direction = Crow.Item("Direction")
        _DeBounceCycles = Crow.Item("DebounceCount")
        _SkipCounter = Crow.Item("SkipCount")
        _Active = Crow.Item("Active")
        _AlarmState = Crow.Item("AlarmState")
        _AlarmActionID = Crow.Item("AlarmActionID")
        _SafeActionID = Crow.Item("SafeActionID")
        _StateStartTime = Now
    End Sub
#End Region

    Public Enum dPorts
        FIO0 = 0
        FIO1 = 1
        FIO2 = 2
        FIO3 = 3
        FIO4 = 4
        FIO5 = 5
        FIO6 = 6
        FIO7 = 7
        EIO0 = 8
        EIO1 = 9
        EIO2 = 10
        EIO3 = 11
        EIO4 = 12
        EIO5 = 13
        EIO6 = 14
        EIO7 = 15
        CIO0 = 16
        CIO1 = 17
        CIO2 = 18
        CIO3 = 19
    End Enum

#Region "Properties Here"

    Private _DeviceID As Integer
    Public Property DeviceID() As Integer
        Get
            Return _DeviceID
        End Get
        Set(ByVal value As Integer)
            _DeviceID = value
        End Set
    End Property

    Private _PortID As dPorts
    Public Property PortID() As dPorts
        Get
            Return _PortID
        End Get
        Set(ByVal value As dPorts)
            _PortID = value
        End Set
    End Property

    Private _PortType As String
    Public Property PortType() As String
        Get
            Return _PortType
        End Get
        Set(ByVal value As String)
            _PortType = value
        End Set
    End Property

    Private _Direction As String
    Public Property Direction() As String
        Get
            Return _Direction
        End Get
        Set(ByVal value As String)
            _Direction = value
        End Set
    End Property

    Private _DeBounceCycles As Byte
    Public Property DeBounceCycles() As Byte
        Get
            Return _DeBounceCycles
        End Get
        Set(ByVal value As Byte)
            _DeBounceCycles = value
        End Set
    End Property

    Private _SkipCounter As Byte = 0
    Public Property SkipCounter() As Byte
        Get
            Return _SkipCounter
        End Get
        Set(ByVal value As Byte)
            _SkipCounter = value
        End Set
    End Property

    Private _Active As Boolean = True
    Public Property Active() As Boolean
        Get
            Return _Active
        End Get
        Set(ByVal value As Boolean)
            _Active = value
        End Set
    End Property

    Private _AlarmState As Boolean
    Public Property AlarmState() As Boolean
        Get
            Return _AlarmState
        End Get
        Set(ByVal value As Boolean)
            _AlarmState = value
        End Set
    End Property

    Private _AlarmActionID As Integer
    Public Property AlarmActionID() As Integer
        Get
            Return _AlarmActionID
        End Get
        Set(ByVal value As Integer)
            _AlarmActionID = value
        End Set
    End Property

    Private _SafeActionID As Integer
    Public Property SafeActionID() As Integer
        Get
            Return _SafeActionID
        End Get
        Set(ByVal value As Integer)
            _SafeActionID = value
        End Set
    End Property

    Private _TimeInState As TimeSpan    'This is an enhancement that I will impliment in the next rev or 2
    Public ReadOnly Property TimeInState() As TimeSpan
        Get
            _TimeInState = Now - _StateStartTime
            Return _TimeInState
        End Get
    End Property

    Private _CyclesInState As Long
    Public ReadOnly Property CyclesInState() As Long
        Get
            Return _CyclesInState
        End Get
    End Property

    Public ReadOnly Property Status() As Boolean
        Get
            Return _ReportedState
        End Get
    End Property

#End Region

#Region "Public Methods"
    ''' <summary>
    ''' Process
    ''' </summary>
    ''' <remarks>Routine to process the Current State of the DI
    ''' Uses processing rules DeBounce Cycles and SkipCount
    ''' See their definitions for more info on these rules</remarks>
    Public Sub Process()
        If Not _Active Then Exit Sub

        If _CurrentSkipCounter <= 0 Then 'This will be > 0 if we have it active
            Dim dState As Boolean
            eDI(iHandle, _PortID, dState)   'This is a call to the LabJack Library
            'Now check to see if we are in debounce
            If dState <> _CurrentState Then ' We have a change
                If _DeBounceCycles = 0 Then
                    _ReportedState = dState
                    _CurrentState = dState
                    _CyclesInState = 1
                    _StateStartTime = Now
                    If dState = _AlarmState Then
                        RaiseEvent StateChange(_PortID, _AlarmActionID, _ReportedState, TimeInState)
                    Else
                        RaiseEvent StateChange(_PortID, _SafeActionID, _ReportedState, TimeInState)
                    End If
                Else
                    _CurrentDebounce = _DeBounceCycles
                    _CurrentState = dState 'OK the counter is set, now lets see 
                    'if it holds for the number of cycles
                End If
            Else
                If _CurrentDebounce > 0 Then 'We should be using it
                    _CurrentDebounce -= 1
                    If _CurrentDebounce <= 0 Then
                        _ReportedState = dState
                        _CurrentState = dState
                        _CyclesInState = 1
                        _StateStartTime = Now
                        If dState = _AlarmState Then
                            RaiseEvent StateChange(_PortID, _AlarmActionID, _ReportedState, TimeInState)
                        Else
                            RaiseEvent StateChange(_PortID, _SafeActionID, _ReportedState, TimeInState)
                        End If
                    End If
                End If
            End If
                'Reset the SkipCounter
                _CurrentSkipCounter = SkipCounter
        Else '(CurrentSkipCounter <= 0)
            _CurrentSkipCounter -= 1 'Count it down one (Only should get here is it was <> 1
        End If '(CurrentSkipCounter <= 0)
        _CyclesInState += 1
    End Sub

#End Region

End Class


